#include "VStdAfx.h"
#include "VMeshUtility.h"



//
//	http://www.terathon.com/code/tangent.html
// TODO http://www.crytek.com/download/Triangle_mesh_tangent_space_calculation.pdf
void VCalculateTangentBasis(const float* P0, const float* P1, const float* P2,
	const float* UV0, const float* UV1, const float* UV2, 
	VVector4& OutTangent, VVector3& Binormal)
{
	const VVector3 Pos0(P0);
	const VVector3 Pos1(P1);
	const VVector3 Pos2(P2);
	const VVector2 TexCoord0(UV0);
	const VVector2 TexCoord1(UV1);
	const VVector2 TexCoord2(UV2);


	VVector3 Edge01 = Pos1 - Pos0;
	VVector3 Edge02 = Pos2 - Pos0;
	VVector2 DeltaUV1 = TexCoord1 - TexCoord0;
	VVector2 DeltaUV2 = TexCoord2 - TexCoord0;
	VVector3 Normal = Edge01.Cross(Edge02);
	Normal.Normalize();
	VVector3 Tangent;

	float Div = DeltaUV1.x*DeltaUV2.y - DeltaUV1.y*DeltaUV2.x;

	if (VAbs(Div) > VEPS)
	{
		Div = 1.0f / Div;
		Tangent = Edge01 * DeltaUV2.y  - Edge02 *DeltaUV1.y; 
		Binormal = Edge02 * DeltaUV1.x  - Edge01 *DeltaUV2.x; 

	}else
	{
		Tangent.Set(1.0f,0.0f,0.0f);
		Binormal.Set(0.0f,1.0f,0.0f);
	}


	VVector3 TNormal = Tangent.Cross(Binormal);
	float DotProd = TNormal.Dot(Normal);

#if 1
	if (DotProd < 0.0f)
	{
		Binormal = Tangent.Cross(Normal);
		Tangent = Normal.Cross(Binormal);
		Tangent.Normalize();
		OutTangent.Set(Tangent, -1.0f);
	}else
	{
		Binormal = Normal.Cross(Tangent);
		Tangent = Binormal.Cross(Normal);
		Tangent.Normalize();
		OutTangent.Set(Tangent, -1.0f);
	}
#else 
	// project tangent to normal plane
	Tangent = (Tangent - Normal * Tangent.Dot(Normal));
	Tangent.Normalize();
	Binormal = Normal.Cross(Tangent);
	OutTangent.Set(Tangent, DotProd < 0.0f ? -1.0f : 1.0f);
#endif 

}

